import UIKit

extension Array  {

//    func filter(newArray: () -> NSArray, searchText: String, filters: String...) -> ()-> [AnyObject] {
//        let substitutionVariables = ["QUERY": searchText]
//        var format = ""
//        
//        for filter in filters {
//            format = format + "(SELF." + filter + " CONTAINS[cd] $QUERY) "
//            if filter != filters.last {
//                format = format + "OR "
//            }
//        }
//        
//        let predicate = NSPredicate(format: format).predicateWithSubstitutionVariables(substitutionVariables)
//        
//        let tmpArray: NSArray = newArray()
//        let result: ()->[AnyObject] = {
//            tmpArray.filteredArrayUsingPredicate(predicate)
//        }
//        
//        return result
//    }
    
    /**
     删除数组中指定的元素
     - parameter tranform: 条件
     
     - returns: 剩余值
     */
    func removeObject(tranform: Element -> Bool) -> [Element]{
        var result: [Element] = self
        
        for (index, object) in result.enumerate() where tranform(object) {
            result.removeAtIndex(index)
            break
        }
        
        return result
    }
    
    /**
     取出指定数量的值
     - parameter sIndex: 起始位置
     - parameter length: 结束位置
     
     - returns: 返回数组第几位开始的后几位值
     - example: alphabet[1, 3], 从第1位开始取3个值
     */
    subscript(sIndex: Int, length: Int) -> [Element] {
        var result: [Element] = []
        for i in sIndex..<sIndex+length {
            result.append(self[i])
        }
        
        return result
    }
    
    /**
     数组一定范围内的值
     - parameter subRange: 范围
     
     - returns: 返回数组指定范围内的所有值
     - example: alphabet[1...3], 从第1位开始取到第3个值
     */
    subscript(tt_subRange subRange: Range<Int>) -> [Element] {
        var result: [Element] = []
        for i in subRange.startIndex..<subRange.endIndex {
            result.append(self[i])
        }
        
        return result
    }
}

// MARK: Array - other
extension Array {
    
    // MARK: reduce
    func tt_reduce<T>(defaultValue: T, combine: (a: T, b: Element)-> T) -> T {
        var result: T = defaultValue
        
        for elment in self {
            result = combine(a: result, b: elment)
        }
        
        return result
    }
    
    // MARK: map
    /**
     这中写法不可行, 不过也不是全部的不可行, 如果self是一个对象数组, 需要返回对象的属性类型就不行了, 下面注释的***_E同理
     */
    //    func tt_map_E(transform: Element -> Element) -> [Element] {
    //        var result: [Element] = []
    //
    //        for i in self {
    //            result.append(transform(i))
    //        }
    //
    //        return result
    //    }
    
    func tt_map_T<T>(transform: Element -> T) -> [T] {
        var result: [T] = []
        
        for i in self {
            result.append(transform(i))
        }
        
        return result
    }
    
    func tt_map_reduce_E(transform: Element -> Element) -> [Element] {
        return tt_reduce([]) { $0 + [$1] }
    }
    
    func tt_map_reduce_T<T>(transform: Element -> T) -> [T] {
        
        return tt_reduce([], combine: { (a, b)  in a + [transform(b)] })
    }
    
    // MARK: filter
    func tt_filter(transform: Element -> Bool) -> [Element] {
        var result: [Element] = []
        for element in self where transform(element)  {
            result.append(element)
        }
        
        return result
    }
    
    /**
     数组过滤
     - 把element节点传入到block里面返回 element节点的类型变量
     - returns:  返回过滤之后的数组
     */
    func tt_filter_reduce_E(transform: Element -> Bool) -> [Element] {
        return tt_reduce([]) { transform($1) ? $0 + [$1] : $0 }
    }
    
    func tt_filter_reduce_T<T>(transform: Element -> (b: Bool,c: T)) -> [T] {
        return tt_reduce([], combine: { (a, b) in transform(b).b ? a + [transform(b).c] : a })
    }
    
    // MARK: flatMap
    /**
     将多维数组平面化
     闭包的作用: 闭包传入到外面, 外面可以对其N维数组操作, 在把数组传回, 在其内部把每组加到一个新的数组中
     */
    func tt_flatMap<T>(tranform: Element -> [T]) -> [T] {
        var result: [T] = []
        for element in self {
            result.appendContentsOf(tranform(element))
        }
        return result
    }
    
    /** 同 tt_flatMap */
    func tt_flatMap_reduce<T>(transform: Element -> [T]) -> [T] {
        return tt_reduce([]) { (a, b) in a + transform(b) }
    }
}
